package com.zipking.cloud.springbootmybatis.config;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.zipking.cloud.springbootmybatis.model.TaskWrapper;
import com.zipking.cloud.springbootmybatis.service.ITask;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
public class Async {
    public static ThreadFactory defaultThreadFactory() {
        return new DefaultThreadFactory();
    }

    static class DefaultThreadFactory implements ThreadFactory {
        private static final AtomicInteger poolNumber = new AtomicInteger(1);
        private final ThreadGroup group;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;

        DefaultThreadFactory() {
            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() :
                    Thread.currentThread().getThreadGroup();
            namePrefix = "xy-pool-" +
                    poolNumber.getAndIncrement() +
                    "-thread-";
        }

        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(group, r,
                    namePrefix + threadNumber.getAndIncrement(),
                    0);
            if (t.isDaemon())
                t.setDaemon(false);
            if (t.getPriority() != Thread.NORM_PRIORITY)
                t.setPriority(Thread.NORM_PRIORITY);
            return t;
        }
    }

    private static volatile Thread qryThread;
    private static volatile Thread submitThread;
    public static volatile boolean runFlag;
    private static volatile boolean waitFlag;
    private final AtomicInteger runCount = new AtomicInteger(1);


    public static void setQryThread(Thread qryThread) {
        Async.qryThread = qryThread;
    }

    public static void setSubmitThread(Thread submitThread) {
        Async.submitThread = submitThread;
    }

    public static void setRunFlag(boolean runFlag) {
        Async.runFlag = runFlag;
    }

    public static void setWaitFlag(boolean waitFlag) {
        Async.waitFlag = waitFlag;
    }

    private static final ThreadPoolExecutor COMMON_POOL =
            new ThreadPoolExecutor(6, 6,
                    15L, TimeUnit.SECONDS,
                    new LinkedBlockingQueue<Runnable>(),
                    Async.defaultThreadFactory(),
                    new ThreadPoolExecutor.CallerRunsPolicy());

    public static <T> void startSingleWhile(ITask<T> task, TaskWrapper<T> taskWrapper) {
        synchronized (Async.class) {
            if (qryThread == null) {
                setQryThread(new Thread(() -> {
                    while (true) {
                        task.run(taskWrapper);
                        if (shutDownJudge()) {
                            break;
                        }
                        sleep(100);
                    }
                }, "singleThread"));
                qryThread.start();
            }
        }
    }

    private static void sleep(long timeout) {
        try {
            TimeUnit.MILLISECONDS.sleep(timeout);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    private static boolean shutDownJudge() {
        if (runFlag) {
            return true;
        }
        return false;
    }

    public static <T> void startThreadPool(ITask<T> task, TaskWrapper<T> taskWrapper) {
        synchronized (Async.class) {
            if (submitThread == null) {
                setSubmitThread(new Thread(() -> {
                    ExecutorCompletionService<Integer> completionService = new ExecutorCompletionService<>(COMMON_POOL);
                    while (true) {
                        try {
                            completionService.submit(() -> {
                                task.run(taskWrapper);
                                return 1;
                            });
                            completionService.poll(1, TimeUnit.SECONDS);
                            setWaitFlag(true);
                            sleep(100);
                        } catch (Exception e) {
                            log.error(e.getMessage(), e);
                        }
                    }
                }));
                submitThread.start();
            }
        }
    }

    public static <T> void startPoolInSingleThread(ITask<T> task, TaskWrapper<T> taskWrapper) {
        List<T> taskList = taskWrapper.getTaskList();
        ExecutorCompletionService<Integer> completionService = new ExecutorCompletionService<>(COMMON_POOL);
        for (T taskBean : taskList) {
            completionService.submit(() -> {
                taskWrapper.setTaskBean(taskBean);
                task.run(taskWrapper);
                return 1;
            });
//            sleep(CommonDef.SUBMIT_THREAD_INTERVAL);
        }
        for (int i = 0; i < taskList.size(); i++) {
            try {
                completionService.poll(10, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public static void main(String[] args) {
        ThreadFactory guavaFactory = new ThreadFactoryBuilder().setNameFormat("guava-pool-").build();


        ExecutorService exec = new ThreadPoolExecutor(1, 1,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>(100),guavaFactory );
        exec.submit(() -> {
            log.info("--记忆中的颜色是什么颜色---");
        });
    }
}

